/**
 * 
 */
package net.bingosoft.common.server;

import java.io.File;
import java.io.FilenameFilter;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.List;

import net.bingosoft.common.config.Config;
import net.bingosoft.common.util.FileHelper;
import sun.misc.Launcher;


/**
 * 2008-1-9 下午02:10:23
 * Author:yangdongyu(yangdy@bingosoft.net)
 * ReadMe:系统入口,用来启动Tomcat服务器,为了能够正常启动Tomcat,请正确配置config.properties中关于tomcat的配置
 * ChangeLog:
 */
public class Starter {
	private static String CATALINA_HOME = FileHelper.getFilePath(Config.getString("CATALINA_HOME","Embedded/Tomcat"));
	
	public static void start() {
		try {
			File libDir = new File(CATALINA_HOME + "\\server\\lib");
			String libPath = libDir.getAbsolutePath();
			if(libDir.exists() && libDir.isDirectory()){
				String [] jars = libDir.list(new FilenameFilter(){
					public boolean accept(File dir, String name) {
						return name.endsWith(".jar");
					}					
				});
				for(String jarFileName : jars ){
					ServerLibClassLoder.addClassPath(libPath+"\\"+jarFileName);	
				}
			}
			EmbeddedTomcat.getInstance().run();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
		start();
	}
	/**
	 * 2008-3-17 下午03:26:13
	 * Author:yangdongyu(yangdy@bingosoft.net)
	 * ReadMe:动态加载tomcat服务器启动所需要的jar包
	 * ChangeLog:
	 */
	static class ServerLibClassLoder{
		 //----------------------------------------------------------------------
	    
	    private static Field classes;
	    private static Method addURL;
	    static {
	        try {
	            classes = ClassLoader.class.getDeclaredField("classes");
	            addURL = URLClassLoader.class.getDeclaredMethod("addURL",new Class[] { URL.class });
	        } catch (Exception e) {
	            e.printStackTrace();
	        }
	        classes.setAccessible(true);
	        addURL.setAccessible(true);
	    }

	    private static URLClassLoader system = (URLClassLoader) getSystemClassLoader();

	    private static URLClassLoader ext = (URLClassLoader) getExtClassLoader();

	    public static ClassLoader getSystemClassLoader() {
	        return ClassLoader.getSystemClassLoader();
	    }

	    public static ClassLoader getExtClassLoader() {
	        return getSystemClassLoader().getParent();
	    }

	    public static List getClassesLoadedBySystemClassLoader() {
	        return getClassesLoadedByClassLoader(getSystemClassLoader());
	    }

	    public static List getClassesLoadedByExtClassLoader() {
	        return getClassesLoadedByClassLoader(getExtClassLoader());
	    }

	    public static List getClassesLoadedByClassLoader(ClassLoader cl) {
	        try {
	            return (List) classes.get(cl);
	        } catch (Exception e) {
	            //throw new RootException(e);
	            e.printStackTrace();
	            return null;
	       }
	    }

	    public static URL[] getBootstrapURLs() {
	        return Launcher.getBootstrapClassPath().getURLs();
	    }

	    public static URL[] getSystemURLs() {
	        return system.getURLs();
	    }

	    public static URL[] getExtURLs() {
	        return ext.getURLs();
	    }

	    private static void list(PrintStream ps, URL[] classPath) {
	        for (int i = 0; i < classPath.length; i++) {
	            ps.println(classPath[i]);
	        }
	    }

	    public static void listBootstrapClassPath() {
	        listBootstrapClassPath(System.out);
	    }

	    public static void listBootstrapClassPath(PrintStream ps) {
	        ps.println("BootstrapClassPath:");
	        list(ps, getBootstrapClassPath());
	    }

	    public static void listSystemClassPath() {
	        listSystemClassPath(System.out);
	    }

	    public static void listSystemClassPath(PrintStream ps) {
	        ps.println("SystemClassPath:");
	        list(ps, getSystemClassPath());
	    }

	    public static void listExtClassPath() {
	        listExtClassPath(System.out);
	    }

	    public static void listExtClassPath(PrintStream ps) {
	        ps.println("ExtClassPath:");
	        list(ps, getExtClassPath());
	    }

	    public static URL[] getBootstrapClassPath() {
	        return getBootstrapURLs();
	    }

	    public static URL[] getSystemClassPath() {
	        return getSystemURLs();
	    }

	    public static URL[] getExtClassPath() {
	        return getExtURLs();
	    }

	    public static void addURL2SystemClassLoader(URL url) {
	        try {
	            addURL.invoke(system, new Object[] { url });
	        } catch (Exception e) {
	            //throw new RootException(e);
	            e.printStackTrace();
	        }
	    }

	    public static void addURL2ExtClassLoader(URL url) {
	        try {
	            addURL.invoke(ext, new Object[] { url });
	        } catch (Exception e) {
	            e.printStackTrace();
	        }
	    }

	    public static void addClassPath(String path) {
	        addClassPath(new File(path));
	    }

	    public static void addExtClassPath(String path) {
	        addExtClassPath(new File(path));
	    }

	    public static void addClassPath(File dirOrJar) {
	        try {
	            addURL2SystemClassLoader(dirOrJar.toURL());
	        } catch (MalformedURLException e) {
	            e.printStackTrace();
	        }
	    }

	    public static void addExtClassPath(File dirOrJar) {
	        try {
	            addURL2ExtClassLoader(dirOrJar.toURL());
	        } catch (MalformedURLException e) {
	            e.printStackTrace();
	        }
	    }
	}
}
